package com.light.mytext.thread

import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.light.mytext.R
import kotlinx.android.synthetic.main.activity_thread_pool.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledThreadPoolExecutor
import java.util.concurrent.TimeUnit


/**
 * 线程池
 * https://blog.csdn.net/IT666DHW/article/details/78832010?utm_source=blogxgwz8&utm_medium=distribute.pc_relevant.none-task-blog-title-4&spm=1001.2101.3001.4242
 */
class ThreadPoolActivity : AppCompatActivity(), View.OnClickListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_thread_pool)
        init_Listener()
    }

    fun init_Listener() {
        bt_pool1.setOnClickListener(this)
        bt_pool2.setOnClickListener(this)
        bt_pool3.setOnClickListener(this)
        bt_pool4.setOnClickListener(this)
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.bt_pool1 -> {//newSingleThreadExecutor
                tv_reult.text=""
                /**
                 * 单个线程的线程池，即线程池中每次只有一个线程工作，单线程串行执行任务 这个线程池只有一个线程在工作，
                也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束，那么会有一个新的线程来替代它。
                此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
                 * 结果：
                 * pool-1-thread-1正在执行....
                 * pool-1-thread-1正在执行....
                 * pool-1-thread-1正在执行....
                 * pool-1-thread-1正在执行....
                 * pool-1-thread-1正在执行....
                 */
                //创建一个可重用固定线程数的线程池
                val pool: ExecutorService = Executors.newSingleThreadExecutor()
                //创建实现了Runnable接口对象，Thread对象当然也实现了Runnable接口;
                val t1: Thread = MyThread()
                val t2: Thread = MyThread()
                val t3: Thread = MyThread()
                val t4: Thread = MyThread()
                val t5: Thread = MyThread()
                //将线程放到池中执行；
                pool.execute(t1)
                pool.execute(t2)
                pool.execute(t3)
                pool.execute(t4)
                pool.execute(t5)
                //关闭线程池
                pool.shutdown()
            }
            R.id.bt_pool2 -> {//newFixedThreadPool
                tv_reult.text=""
                /**
                 * 创建固定大小的线程池。每次提交一个任务就创建一个线程，直到线程达到线程池的最大大小。
                 * 线程池的大小一旦达到最大值就会保持不变，如果某个线程因为执行异常而结束，那么线程池会补充一个新线程。
                 *pool-1-thread-1正在执行....
                pool-1-thread-1正在执行....
                pool-1-thread-1正在执行....
                pool-1-thread-1正在执行....
                pool-1-thread-2正在执行....
                 */
                //创建一个可重用固定线程数的线程池
                var pool: ExecutorService? =
                    Executors.newFixedThreadPool(3)
                //创建实现了Runnable接口对象，Thread对象当然也实现了Runnable接口;
                val t1: Thread = MyThread()
                val t2: Thread = MyThread()
                val t3: Thread = MyThread()
                val t4: Thread = MyThread()
                val t5: Thread = MyThread()
                //将线程放到池中执行；
                pool!!.execute(t1)
                pool.execute(t2)
                pool.execute(t3)
                pool.execute(t4)
                pool.execute(t5)
                //关闭线程池
                pool.shutdown()
            }
            R.id.bt_pool3 -> {//newCachedThreadPool
                tv_reult.text=""
                /**
                 * 创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程，
                那么就会回收部分空闲（60秒不执行任务）的线程，当任务数增加时，此线程池又可以智能的添加新线程来处理任务。
                此线程池不会对线程池大小做限制，线程池大小完全依赖于操作系统（或者说JVM）能够创建的最大线程大小。
                pool-1-thread-2正在执行....
                pool-1-thread-1正在执行....
                pool-1-thread-3正在执行....
                pool-1-thread-4正在执行....
                pool-1-thread-5正在执行....
                 */
                //创建一个可重用固定线程数的线程池
                val pool =
                    Executors.newCachedThreadPool()
                //创建实现了Runnable接口对象，Thread对象当然也实现了Runnable接口;
                val t1: Thread = MyThread()
                val t2: Thread = MyThread()
                val t3: Thread = MyThread()
                val t4: Thread = MyThread()
                val t5: Thread = MyThread()
                //将线程放到池中执行；
                pool.execute(t1)
                pool.execute(t2)
                pool.execute(t3)
                pool.execute(t4)
                pool.execute(t5)
                //关闭线程池
                pool.shutdown()
            }
            R.id.bt_pool4 -> {//newScheduledThreadPool
                tv_reult.text=""
                /**
                 * 创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
                ===================
                23119318857491
                23121319071841
                23129318176148
                23123319007891
                ===================
                23125318176937
                23127318190359
                ===================
                23131318344312
                23133318465896
                ===================
                23135319645812
                 */
                var exec: ScheduledThreadPoolExecutor = ScheduledThreadPoolExecutor(1)
                exec.scheduleAtFixedRate(
                    Runnable //每隔一段时间就触发异常
                    {
                        // TODO Auto-generated method stub
                        println("===================")
                    }, 1000, 5000, TimeUnit.MILLISECONDS
                )

                exec.scheduleAtFixedRate(
                    Runnable //每隔一段时间打印系统时间，证明两者是互不影响的
                    {
                        // TODO Auto-generated method stub
                        println(System.nanoTime())
                    }, 1000, 2000, TimeUnit.MILLISECONDS
                )
            }
        }

    }

    inner class MyThread : Thread() {
        override fun run() {
            super.run()
            var name=currentThread().name
            tv_reult.post {
                var str=StringBuffer("")
                str.append(tv_reult.text.toString()).append("\n").append(name + "正在执行....")
                tv_reult.text=str.toString()
            }
            println(name + "正在执行....");
        }

    }


}
